﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using StandardDAC.Base;
using System.Data.OleDb;

namespace StandardDAC.OleDb {
    public abstract class OleDac {
        string connectionString = null;
        public string ConnectionString {
            get {
                if (connectionString == null)
                    connectionString = GetConnectionString();
                return connectionString;
            }
        }
        protected ConnInfo ConnInfo() {
            return new ConnInfo(ConnectionString);
        }
        protected abstract string GetConnectionString();

        private OleDbController sql = new OleDbController();
        protected OleDbController Sql {
            get { return sql; }
        }

        public void Save(IDataModel o, string table) {
            bool isNew = o.IsNew();
            object output = Sql.SaveObject(ConnInfo(), o,
                isNew ? table + "_Create" : table + "_Update", isNew);
            if (isNew && output != null)
                o.Id = (int)output;
        }
        public void Delete(object o, string table) {
            Sql.DeleteObject(ConnInfo(), o, table + "_Delete");
        }
        public void ReadById<T>(T item, string table, List<string> allParametersOfReadProcInOrder) {

            Sql.GetObjectById<T>(allParametersOfReadProcInOrder, ConnInfo(), table + "_Read", item);
        }

        public List<T> ReadAll<T>(string table, List<string> allParametersOfReadProcInOrder) {
            return Sql.GetCollection<T>(allParametersOfReadProcInOrder, ConnInfo(), table + "_Read");
        }
        public List<T> ReadByParams<T>(string table, OleDbParameter parameter, List<string> allParametersOfReadProcInOrder) {
            return Sql.GetCollection<T>(allParametersOfReadProcInOrder, ConnInfo(), table + "_Read", new OleDbParameter[] { parameter });
        }
        public List<T> ReadByParams<T>(string table, OleDbParameter[] parameters, List<string> allParametersOfReadProcInOrder) {
            return Sql.GetCollection<T>(allParametersOfReadProcInOrder, ConnInfo(), table + "_Read", parameters);
        }

        public ModelKeyedCollection<T> ReadKeyedAll<T>(string table, List<string> allParametersOfReadProcInOrder)
            where T : IDataModel {
            ModelKeyedCollection<T> collection = new ModelKeyedCollection<T>();
            Sql.AddToCollection<T>(allParametersOfReadProcInOrder, ConnInfo(), table + "_Read", collection);
            return collection;
        }
        public ModelKeyedCollection<T> ReadKeyedByParams<T>(string table, OleDbParameter parameter, List<string> allParametersOfReadProcInOrder)
            where T : IDataModel {
            ModelKeyedCollection<T> collection = new ModelKeyedCollection<T>();
            Sql.AddToCollection<T>(allParametersOfReadProcInOrder, ConnInfo(), table + "_Read", new OleDbParameter[] { parameter }, collection);
            return collection;
        }
        public ModelKeyedCollection<T> ReadKeyedByParams<T>(string table, OleDbParameter[] parameters, List<string> allParametersOfReadProcInOrder)
            where T : IDataModel {
            ModelKeyedCollection<T> collection = new ModelKeyedCollection<T>();
            Sql.AddToCollection<T>(allParametersOfReadProcInOrder, ConnInfo(), table + "_Read", parameters, collection);
            return collection;
        }

        public DataSet GetDataSet(string procedure, OleDbParameter[] parameters) {
            return Sql.GetDataSet(ConnInfo(), procedure, parameters);
        }
        public DataTable GetDataTable(string procedure, OleDbParameter[] parameters) {
            return Sql.GetTable(ConnInfo(), procedure, parameters);
        }
        public DataRow GetDataRow(string procedure, OleDbParameter[] parameters) {
            return Sql.GetRow(ConnInfo(), procedure, parameters);
        }


        OleDbTransaction currentTran;//current transaction (usually null)
        public OleDbTransaction Transaction {
            get { return currentTran; }
        }
        protected TranInfo CurrentTranInfo() {
            if (currentTran == null) {
                currentTran = (OleDbTransaction)Sql.NewTransaction(connectionString);
            }
            return new TranInfo(currentTran);
        }

        public void Execute(string procedure, OleDbParameter[] parameters) {
            Sql.Execute(ConnInfo(), procedure, parameters);
        }
        public DataSet ExecuteInTransaction(string procedure, OleDbParameter[] parameters) {
            return Sql.GetDataSet(CurrentTranInfo(), procedure, parameters);
        }
        public DataSet InlineSql_Execute(string sqlString, OleDbParameter[] parameters) {
            return Sql.InlineSql_Execute(ConnInfo(), sqlString, parameters);
        }
        public DataSet InlineSql_ExecuteInTransaction(string sqlString, OleDbParameter[] parameters) {
            return Sql.InlineSql_Execute(CurrentTranInfo(), sqlString, parameters);
        }
        public OleDbTransaction TransactionCommit() {
            OleDbTransaction retValue = currentTran;
            if (currentTran != null) {
                currentTran.Commit();
                currentTran = null;
            }
            return retValue;
        }
        public OleDbTransaction TransactionRollback() {
            OleDbTransaction retValue = currentTran;
            if (currentTran != null) {
                currentTran.Rollback();
                currentTran = null;
            }
            return retValue;
        }


        #region public methods - helpers [STATIC]
        public static OleDbParameter newInParam(string name, object value) {
            OleDbParameter p = new OleDbParameter(name, value);
            return p;
        }
        public static OleDbParameter newInParam(string name, OleDbType type, object value) {
            OleDbParameter p = new OleDbParameter(name, value);
            p.OleDbType = type;
            return p;
        }
        public static OleDbParameter newOutParam(string name, OleDbType type) {
            OleDbParameter p = new OleDbParameter(name, type);
            p.Direction = ParameterDirection.Output;
            return p;
        }
        #endregion

        #region IDisposable Members
        /// <summary>
        /// Commits any current transactions that were opened. If you don't use transactions explicitly, then
        /// they aren't created.
        /// </summary>
        public void Dispose() {
            if (currentTran != null && currentTran.Connection != null) {
                currentTran.Commit();
                currentTran.Connection.Dispose();
            }
        }

        #endregion

    }
}